/*
 * @Author: 天桥底下说书的 179946422@qq.com
 * @Date: 2024-05-14 21:04:37
 * @LastEditors: 天桥底下说书的 179946422@qq.com
 * @LastEditTime: 2024-05-15 13:51:22
 * @FilePath: \esp32-assistant\src\main.cpp
 * @Description:
 *
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
 */
#include <Arduino.h>
#include "AudioTools.h"
#include "AudioLibs/AudioSourceLittleFS.h"
#include "AudioCodecs/CodecMP3Helix.h"
#include "Communication/UDPStream.h"
#include "MyButton.h"
#include "MyLog.h"
#include "MyLed.h"
#include "config.h"

#define AI_USE_SPEAKER
#define AI_USE_MIC

// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char *ssid = WIFI_SSID;
const char *password = WIFI_PASSWORD;

#define UDP_SERVER_PORT 8085
const int udpServerPort = UDP_SERVER_PORT;

// 根据实际连接的引脚进行配置
#define I2S_SPEAKER_BCLK 8  // 时钟信号
#define I2S_SPEAKER_DOUT 17 // 数据输出
#define I2S_SPEAKER_LRC 18  // 声道选择信号

// 扬声器
AudioInfo speakerInfo(16000, 1, 16);
MP3DecoderHelix decoder;
I2SStream speakerStream;
VolumeStream volumeSpeakerStream(speakerStream);

// MP3 音频流
const char *startFilePath = "/";
const char *ext = "mp3";
AudioSourceLittleFS spiffsSource(startFilePath, ext);
AudioPlayer mp3Player(spiffsSource, volumeSpeakerStream, decoder);

// 麦克风
UDPStream udpMic(ssid, password);
AudioInfo micInfo(16000, 1, 16);
I2SStream micStream;
StreamCopy i2s2UdpCopier(udpMic, micStream);

#define I2S_MIC_PORT I2S_NUM_0
#define I2S_SPEAKER_PORT I2S_NUM_1

// 根据实际连接的引脚进行配置
#define I2S_MIC_BCLK 19 // 时钟信号
#define I2S_MIC_DIN 15  // 数据输入
#define I2S_MIC_LRC 47  // 声道选择信号

void play_mp3(String filename)
{
  spiffsSource.setFileFilter(filename.c_str());
  mp3Player.begin();
}

void task_mp3_player_loop(void *pvParameters)
{
  while (true)
  {
    // Log.infoln("palyer:%T", player.isActive());
    mp3Player.copy();
  }
  vTaskDelete(NULL);
}

// 连接wifi
void connectWifi()
{

  WiFi.begin(ssid, password);
  // 等待WiFi连接,成功连接后输出成功信息
  while (WiFi.status() != WL_CONNECTED)
  {
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected!");
  Serial.println("");
}

// 初始化文件系统(LittleFS)
void littleFS_setup()
{
  if (!LittleFS.begin(true))
  {
    Log.errorln("LittleFS 打开失败了！！！");
    if (LittleFS.format())
      Log.infoln("LittleFS 格式化完成。");
  }
  Log.infoln("LittleFS 文件系统正常。");
}

void MySpeaker_setup()
{
  AudioLogger::instance().begin(Serial, AudioLogger::Info);
  // start I2S
  Serial.println("MySpeaker starting I2S...");
  auto config = speakerStream.defaultConfig(TX_MODE);
  config.copyFrom(speakerInfo);
  config.port_no = I2S_SPEAKER_PORT;
  config.pin_bck = I2S_SPEAKER_BCLK;
  config.pin_data = I2S_SPEAKER_DOUT;
  config.pin_ws = I2S_SPEAKER_LRC;
  config.buffer_size = 1024;
  config.buffer_count = 20;
  speakerStream.begin(config);
  volumeSpeakerStream.begin(config);
  volumeSpeakerStream.setVolume(1);
  // mp3Player.setMetadataCallback(callbackPrintMetaData);
  Serial.println("MySpeaker started...");
}

// 音频任务
void task_speaker_loop(void *pvParameters)
{
  while (true)
  {
    mp3Player.copy();
  }
  vTaskDelete(NULL);
}

// 麦克风初始化
void MyMic_setup()
{
  udpMic.begin(udpServerAddress, udpServerPort);
  Serial.println("MyMic starting I2S...");
  auto config_in = micStream.defaultConfig(RX_MODE);
  config_in.copyFrom(micInfo);
  config_in.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
  config_in.is_master = true;
  config_in.port_no = I2S_MIC_PORT;
  config_in.pin_bck = I2S_MIC_BCLK;
  config_in.pin_ws = I2S_MIC_LRC;
  config_in.pin_data = I2S_MIC_DIN;
  // 是否设定use_apll均可正常工作
  config_in.use_apll = false;
  micStream.begin(config_in);
  // err = i2s_set_clk(I2S_MIC_PORT, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); // Set the clock and bitwidth used by I2S Rx and Tx.// 设置I2S RX、Tx使用的时钟和位宽
  Serial.println("MyMic I2S started...");
}

// 麦克风任务
void task_mic_loop(void *pvParameters)
{
  bool nowState = HIGH;
  bool record = false;
  while (true)
  {
    nowState = digitalRead(GPIO_BOOT_BUTTON);
    // 录音模式
    if (nowState == LOW && !record)
    {
      i2s2UdpCopier.copy();
      record = true;
    }
    else
    {
      if (record)
      {
        Log.infoln("麦克风未录音");
        record = false;
      }
      vTaskDelay(300 / portTICK_PERIOD_MS);
    }
  }
  vTaskDelete(NULL);
}

void setup()
{
  // 日志初始化
  Serial.begin(115200);

  log_setup();

  // Chat按键初始化
  button_setup();

  // 初始化灯
  led_setup();

  // 初始化文件系统
  littleFS_setup();

  // 连接wifi
  connectWifi();

#ifdef AI_USE_SPEAKER

  // 初始化音频
  MySpeaker_setup();
  // 创建音频任务
  xTaskCreatePinnedToCore(task_speaker_loop, "task_speaker_loop", 1024 * 8, NULL, 3, NULL, ARDUINO_RUNNING_CORE);

#endif

#ifdef AI_USE_MIC
  // MIC初始化
  MyMic_setup();
  // MIC声音采集任务
  xTaskCreatePinnedToCore(task_mic_loop, "task_mic_loop", 1024 * 4, NULL, 3, NULL, ARDUINO_RUNNING_CORE);

#endif
}

void loop()
{
  vTaskDelay(10000);
}